/*file chiron src/json.js */
/*preamble

    Copyright (c) 2002-2008 Kris Kowal <http://cixar.com/~kris.kowal>
    MIT License
    
    The license terms are stated in full in <license.rst> and at the end
    of all source files.

*/

/**
    evaluates and formats trusted JavaScript object hierarchies and
    object notation.
*/
var base = require('./base');
var date = require('./date');

var evalGlobal = environment.evalGlobal;
if (!evalGlobal)
    base.print("JSON cannot decode without environment.evalGlobal", "warn");

/*
    returns a JavaScript object hierarchy from 
    trusted JSON text.
*/
exports.decode = function (text) {
    try {
        return evalGlobal('(' + text + ')');
    } catch (exception) {
        throw new Error("JSON format error in " + repr(text));
    }
};

/*
    returns JSON text from a trusted JavaScript
    object hierarchy.
*/
exports.encode = base.operator(1, 'json', function (value) {
    if (base.no(value))
        return 'null';
    if (base.isInstance(value, Boolean))
        return '' + value;
    if (base.isInstance(value, Date))
        return date.format(value, date.isoDateTime);
    if (base.isInstance(value, String))
        return base.enquote(value, true); /* true means strictJson with \u instead of \x */
    if (base.isInstance(value, Number))
        return '' + value;
    if (base.isInstance(value, Array))
        return '[' + base.eachIter(value, exports.encode).join(',') + ']';
    if (base.isInstance(value, Object))
        return '{' + base.dict(value).eachApplyIter(function (key, value) {
            return base.enquote(key) + ':' + base.encode(value);
        }).join(',') + '}';
});

/*** request
*/
exports.request = function (options, callback, errback) {
    var http = require('./http');
    if (callback) {
        http.request(options, function (response) {
            try {
                callback(decode(response.getText()));
            } catch (exception) {
                if (!no(errback)) {
                    errback(response);
                }
            }
        });
    } else {
        return decode(http.requestText(options));
    }
};

/**

    Security
    ========

    Other JSON implementations provide somewhat reliable security barriers,
    although they do little to protect the client against untrusted scripts.
    This module operates on the assumption that you are dealing with trusted
    data.  This is not an absurd assumption, but it is one you must
    make if you use these functions.  Because of this assumption,
    this module provides a flexible JSON formating API and
    high performance JSON evaluation.  Security, however,
    is not in the mix.
    
    The common cases for data
    transfer between a web page client and a server include text transfer
    to and from the same origin using an XML HTTP request (AJAX), and
    cross-site scripts.  If you're using AJAX, you probably trust
    your server, so you can safely execute arbitrary JavaScript
    locally.  In this case, `decode` will suffice for constructing
    object hierarchies from the trusted text.  If you're using
    a cross-site script, you probably can't trust your server, but
    you have already given them complete, compromising access to your
    client scripting environment, so there's little efficacy in attempting
    to sanitize the data you've received.  Also, using a cross-site
    script, you will have no need to evaluate JSON since the browser
    has already done so by executing the script.  The other
    scenario is construction of JSON from untrusted JavaScript objects,
    presumably constructed from your cross-site script.
    Your server has no reason to trust the client in that case or
    otherwise, so any sanitization should occur on the server,
    not in the client.

    If you're using cross-site scripts, this module, nor
    any other method of protection save strong trust, will
    secure your client from malicious data corruption.
    However, this module will provide a modicum of protection
    against accidental tampering with local variables and
    syntactic edge cases that using a raw eval might not.

    
    Transformations and Schema
    ==========================

    Doug Crockford's original implementation accepts
    a filter or transform relation function as an optional
    parameter.  This is a half-measure toward transforming
    JSON hierarchies into full-fledged JavaScript object
    hierarchies including user-defined types.  I've left
    this as an exercise for another module that could
    potentially transform complex hierarchies using
    a schema representing the expected data structure.


    References
    ==========

    http://www.json.org/
    http://www.json.org/json2.js
    http://google-caja.googlecode.com/svn/trunk/src/js/com/google/caja/JSON.js

*/


/*license

    Legal
    =======
    
    Chiron is a component of the Tale web-game project.
    
    See <credit.txt> for a complete list of
    contributions and their licenses.  All contributions are provided
    under permissive, non-viral licenses including MIT, BSD, Creative Commons
    Attribution 2.5, Public Domain, or Unrestricted.
    
    
    License
    =======
    
    Copyright (c) 2002-2008 Kris Kowal <http://cixar.com/~kris.kowal>
    MIT License
    
    
    MIT License
    -----------
    
    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use,
    copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following
    conditions:
    
    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.
    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.

*/

